package mahjong;

import java.util.Random;

/**
 * Main entry point to the mahjong game. Contains only static methods.
 *
 */
public class Main
{
	/** Directory where the individual tiles are found. */
	private static final String TILEDIR = "TexturePacks" + java.io.File.separator + "Default";  
	/** Name of actual tileset file. */
	private static final String TILESET = "tiles.set";  
	/** Name of board layout directory. */
	private static final String BOARDDIR = "Layouts";
	/** Default board layout. */
	private static final String BOARDDEFAULT = "turtle.layout";
	/** Mutable directory where the individual tiles are found. */
	private static String tileDir = TILEDIR + java.io.File.separator;
	/** Mutable name of tileset file. */
	private static String tileSetFile = TILEDIR + java.io.File.separator + TILESET;
	/** Random seed, for repeatability. */
	private static long seed;
	/** Name of board layout file. */
	private static String boardName = BOARDDIR + java.io.File.separator + BOARDDEFAULT;
	/** Batch mode flag. */
	private static boolean batchModeFlag = false;
	/** AI used in batch mode. */
	private static int batchModeAI;
	/** Specifies if solvable boards should be generated in batch mode */
	private static boolean batchModeSolvable;
	/** AI used in batch mode. */
	private static int batchModeIteration;

	/**
	 * @param args Command line arguements.
	 */
	public static void main(String[] args)
	{
		Board b;
		Random r;
		// parse arguments; this will create a board too
		parse(args);
		// construct a board, seeded or really random

		if (seed == 0L) {
			r = null;
		} else {
			r = new Random(seed);
		}

		// start batch mode
		if (batchModeFlag) {
			int win = 0;
			for (int i = 0; i < batchModeIteration; i++) {
				b = new Board(r, boardName, batchModeSolvable);
				b.autoPlay(batchModeAI);
				if (b.isEmpty()) {
					win++;
				}
			}
			System.out.printf("Running %s AI on %d %s boards with %s.\n",
					batchModeAI == 0 ? "cheating" : (batchModeAI == 1 ? "normal" : "simple"),
					batchModeIteration,
					batchModeSolvable ? "solvable" : "random",
					boardName);
			System.out.printf("AI won %d out of %d games, the winning percentage is %f.\n",
					win,
					batchModeIteration,
					100 * ((double) win) / batchModeIteration);
			return;
		}

		// normal game play

		b = new Board(r, boardName);
		// construct the Player and the GUI
		Player p = new Player();
		JViewer v = new JViewer(boardName, b, p);
		p.setBoard(b);
		p.setView(v.getViewer());

		// play the game!
		p.play();
	}

	/**
	 * Displays default usage flags.
	 */
	public static void help()
	{
		System.out.println("Usage: java mahjong.Main [-h | -seed n | -tiledir dir | -tileset tiles.set | -f board.layout]*");
		System.out.println("Where:");
		System.out.println("    -h                 This help");
		System.out.println("    -seed n            Specify random seed");
		if (seed!=0L) 
		{
			System.out.println("                        (currently="+seed+")");
		}
		System.out.println("    -tiledir dir       Directory with tile files (ends in a path separator)");
		System.out.println("                        (currently="+tileDir+")");
		System.out.println("    -tileset filename  Name of file that maps tiles to image files");
		System.out.println("                        (currently="+tileSetFile+")");
		System.out.println("    -f filename        Load the specified board layout");
		System.out.println("                        (currently="+boardName+")");
	}

	/** Method to parse argument array and set appropriate values.
	 * @param args The argument array given to main. 
	 */
	private static void parse(String[] args)
	{
		for (int i = 0; i < args.length; i++) {
			if ("-seed".equals(args[i])) {
				i++;
				try {
					seed = Long.parseLong(args[i]);
				} catch (NumberFormatException nfe) {
					System.out.println(nfe);
					seed = 0L;
				}
				System.out.println("Seed set to "+seed);
			} else if ("-h".equals(args[i])) {
				help();
				System.exit(0);
			} else if ("-f".equals(args[i])) {
				i++;
				boardName = BOARDDIR + java.io.File.separator + args[i];
			} else if ("-tiledir".equals(args[i])) {
				i++;
				tileDir = args[i];
			} else if ("-tileset".equals(args[i])) {
				i++;
				tileSetFile = args[i];
			} else if ("-batch".equals(args[i])) {
				batchModeFlag = true;
				if (++i >= args.length) {
					System.out.println("Please specify AI for batch mode.");
					System.exit(1);
				}
				if ("simple".equals(args[i])) {
					batchModeAI = 3;
				} else if ("cheating".equals(args[i])) {
					batchModeAI = 2;
				} else if ("normal".equals(args[i])) {
					batchModeAI = 1;
				} else if ("montecarlo".equals(args[i])) {
					batchModeAI = 0;
				} else {
					System.out.println("Unrecognized AI: " + args[i]);
					System.exit(1);
				}
				if (++i >= args.length) {
					System.out.println("Please board type batch mode.");
					System.exit(1);
				}
				if ("random".equals(args[i])) {
					batchModeSolvable = false;
				} else if ("solvable".equals(args[i])) {
					batchModeSolvable = true;
				} else {
					System.out.println("Unrecognized board type: " + args[i]);
					System.exit(1);
				}
				if (++i >= args.length) {
					System.out.println("Please the nunber of iteration to be run in batch mode.");
					System.exit(1);
				}
				try {
					batchModeIteration = Integer.parseInt(args[i]);
				} catch (NumberFormatException nfe) {
					System.out.println(nfe);
					System.exit(1);
				}
			} else {
				System.out.println("Unrecognized option: "+args[i]);
				help();
				System.exit(1);
			}
		}
	}

	/** Getter for the the tile set file name.
	 * @return The name of the file containing the tile set description. */
	public static String getTileSetFile()
	{
		return tileSetFile;
	}

	/**
	 * Getter for the tile set directory name.
	 * @return The directory containing the tiles (ends in directory separator).
	 */
	public static String getTileDir()
	{
		return tileDir;
	}
}
